/*
 * Project: BeatifIntredPlayer
 * Copyright © ByUsi
 * Source Code Repository: https://giitee.com/byusi/beatifintredplayer
 */
class BeatifIntredPlayer {
    constructor(options) {
        this.options = Object.assign({
            container: document.body,
            src: '',
            theme: '#00a1d6',
            maxHeightRatio: 0.8,
            minWidth: 320,
            responsive: true,
            loop: false,
            autoplay: false
        }, options);

        // 视频元数据
        this.naturalWidth = 0;
        this.naturalHeight = 0;
        this.aspectRatio = 16 / 9;

        // 初始化核心
        this.initContainer();
        this.initPlayerCore();
        this.initTheme();
        this.bindEvents();
    }

    /* 容器初始化 */
    initContainer() {
        this.container = document.createElement('div');
        this.container.className = 'bip-container';
        Object.assign(this.container.style, {
            position: 'relative',
            margin: '0 auto',
            backgroundColor: '#000',
            overflow: 'hidden',
            transition: 'width 0.3s ease, height 0.3s ease'
        });

        this.videoWrapper = document.createElement('div');
        this.videoWrapper.className = 'bip-video-wrapper';
        this.videoWrapper.style.cssText = `
            width: 100%;
            height: 100%;
        `;

        this.container.appendChild(this.videoWrapper);
        this.options.container.appendChild(this.container);
    }

    /* 初始化播放器核心 */
    initPlayerCore() {
        this.dp = new window.DPlayer({
            container: this.videoWrapper,
            video: {
                url: this.options.src,
                type: this.detectVideoType()
            },
            theme: this.options.theme,
            loop: this.options.loop,
            autoplay: this.options.autoplay,
            customType: {
                flv: (video) => this.initFLVPlayer(video),
                hls: (video) => this.initHLSPlayer(video)
            }
        });

        // 元数据监听
        this.dp.video.addEventListener('loadedmetadata', () => {
            this.naturalWidth = this.dp.video.videoWidth || 1280;
            this.naturalHeight = this.dp.video.videoHeight || 720;
            this.aspectRatio = this.naturalWidth / this.naturalHeight;
            this.updateContainerSize();
            this.initResizeHandler();
        });
    }

    /* 主题系统 */
    initTheme() {
        document.documentElement.style.setProperty('--bip-theme', this.options.theme);
    }

    /* 视频类型检测 */
    detectVideoType() {
        const src = (this.options.src || '').toLowerCase();
        return {
            '.mp4': 'normal',
            '.webm': 'webm',
            '.m3u8': 'hls',
            '.flv': 'flv'
        }[Object.keys({
            '.mp4': 1, '.webm': 1, '.m3u8': 1, '.flv': 1
        }).find(ext => src.endsWith(ext))] || 'auto';
    }

    /* FLV初始化 */
    initFLVPlayer(video) {
        if (!window.flvjs) throw new Error('flv.js未加载');
        this.flvPlayer = window.flvjs.createPlayer({
            type: 'flv',
            url: this.options.src,
            isLive: this.options.src.includes('live')
        });
        this.flvPlayer.attachMediaElement(video);
        this.flvPlayer.load();
    }

    /* HLS初始化 */
    initHLSPlayer(video) {
        if (!window.Hls) throw new Error('hls.js未加载');
        this.hls = new window.Hls();
        this.hls.loadSource(this.options.src);
        this.hls.attachMedia(video);
        this.hls.on(window.Hls.Events.MANIFEST_PARSED, () => video.play());
    }

    /* 尺寸更新逻辑 */
    updateContainerSize() {
        if (!this.options.responsive) return;

        const parentWidth = this.container.parentElement.clientWidth;
        const maxHeight = window.innerHeight * this.options.maxHeightRatio;
        let targetWidth = parentWidth;
        let targetHeight = targetWidth / this.aspectRatio;

        // 高度限制
        if (targetHeight > maxHeight) {
            targetHeight = maxHeight;
            targetWidth = targetHeight * this.aspectRatio;
        }

        // 宽度下限
        targetWidth = Math.max(targetWidth, this.options.minWidth);

        Object.assign(this.container.style, {
            width: `${targetWidth}px`,
            height: `${targetHeight}px`
        });

        this.dp.resize();
    }

    /* 尺寸监听系统 */
    initResizeHandler() {
        this.resizeObserver = new ResizeObserver(() => {
            if (!document.fullscreenElement) this.updateContainerSize();
        });
        this.resizeObserver.observe(this.container.parentElement);
    }

    /* 全屏处理 */
    toggleFullscreen() {
        if (!document.fullscreenElement) {
            this.enterFullscreen();
        } else {
            this.exitFullscreen();
        }
    }

    enterFullscreen() {
        this.container.requestFullscreen?.()
            .then(() => {
                const screenWidth = window.innerWidth;
                const screenHeight = window.innerHeight;
                
                if (screenWidth / screenHeight > this.aspectRatio) {
                    this.container.style.width = `${screenHeight * this.aspectRatio}px`;
                    this.container.style.height = `${screenHeight}px`;
                } else {
                    this.container.style.width = `${screenWidth}px`;
                    this.container.style.height = `${screenWidth / this.aspectRatio}px`;
                }

                Object.assign(this.container.style, {
                    position: 'fixed',
                    top: '50%',
                    left: '50%',
                    transform: 'translate(-50%, -50%)'
                });

                this.dp.resize();
            });
    }

    exitFullscreen() {
        document.exitFullscreen?.()
            .then(() => {
                Object.assign(this.container.style, {
                    position: 'relative',
                    top: 'auto',
                    left: 'auto',
                    transform: 'none'
                });
                this.updateContainerSize();
            });
    }

    /* 事件绑定 */
    bindEvents() {
        // 错误处理
        this.dp.video.addEventListener('error', (e) => {
            this.showError(`播放错误: ${this.getErrorMessage(e)}`);
        });

        // 全屏状态变化
        document.addEventListener('fullscreenchange', () => {
            if (!document.fullscreenElement) {
                this.updateContainerSize();
            }
        });
    }

    getErrorMessage(e) {
        const code = e.target.error?.code;
        return {
            1: '播放中止',
            2: '网络错误',
            3: '解码失败',
            4: '格式不支持'
        }[code] || '未知错误';
    }

    showError(message) {
        const errorBox = document.createElement('div');
        errorBox.className = 'bip-error';
        errorBox.innerHTML = `
            <div class="error-icon">⚠️</div>
            <p>${message}</p>
            <button class="bip-retry" onclick="this.closest('.bip-error').remove()">
                重试播放
            </button>
        `;
        this.container.appendChild(errorBox);
    }

    /* 公开API */
    play() { this.dp.play(); return this; }
    pause() { this.dp.pause(); return this; }
    seek(time) { this.dp.seek(time); return this; }

    destroy() {
        this.resizeObserver?.disconnect();
        [this.flvPlayer, this.hls].forEach(instance => instance?.destroy());
        this.dp.destroy();
        this.container.remove();
    }
}

export default BeatifIntredPlayer;